#pragma once
#include "vn/Socket.h"
#include "vn/IPEndPoint.h"


void SocketTest() {_test_func_;
	{
		Socket a;
	}

	{
		Socket a;
		a.OpenTcp();
		a.Connect("localhost", 8443);
		a.Send("Hello\r\nXinchao", 5);
		a.Shutdown(ShutdownSend);
		Buf8 b[10000];
		a.Recv(b, 10000);
	}

	{
		Socket a;
		REQUIRE_EXCEPTION( a.Connect("localhost", 8443)			);
		REQUIRE_EXCEPTION( a.Connect(IPAddress(10,0,0,5), 8443)		);
		REQUIRE_EXCEPTION( a.Connect(IPEndPoint(IPAddress(10,0,0,5), 8443))	);

		REQUIRE_EXCEPTION( a.Bind(IPEndPoint(IPAddress::Any, 80))	);
		REQUIRE_EXCEPTION( a.Bind(IPAddress::Any, 80)				);

		REQUIRE_EXCEPTION( a.Listen(1)								);

		REQUIRE_EXCEPTION( a.Accept(a)								);
		Buf8 buf[1];
		IPEndPoint rep;
		REQUIRE_EXCEPTION( a.Recv(buf, 1)							);
		REQUIRE_EXCEPTION( a.RecvFrom(buf, 1, 0, rep)				);
		REQUIRE_EXCEPTION( a.Send(buf, 1)							);
		REQUIRE_EXCEPTION( a.SendTo(buf, 1, 0, rep)					);

		REQUIRE_EXCEPTION( a.Shutdown(ShutdownBoth)						);

		// after many faille operations, the socket still close:
		assert(a.m_Status == StatusClose);

		a.Close();

		//Buf8 arg[100];
		//REQUIRE_EXCEPTION( IOControl(1, buf)						);

		REQUIRE_EXCEPTION( a.GetLingerState()						);
		LINGER lg = {0};
		REQUIRE_EXCEPTION( a.SetLingerState(lg)						);

		a.OpenTcp();
		REQUIRE_EXCEPTION( a.OpenTcp()		);
		a.Close();
		a.OpenUdp();
		a.Close();
	}

	// status of tcp client socket
	{
		Socket a;
		assert(a.m_Status == StatusClose);
		a.OpenTcp();
		assert(a.m_Status == StatusOpen);

		REQUIRE_EXCEPTION( a.Connect("non_exist_domain", 80) );
		assert(a.m_Status == StatusOpen);	// still open, not connected yet

		a.Connect("localhost", 8443);
		assert(a.m_Status == StatusConnected);

		a.Close();
		assert(a.m_Status == StatusClose);
	}

	// status of tcp server socket
	{
		Socket a;
		assert(a.m_Status == StatusClose);
		a.OpenTcp();
		assert(a.m_Status == StatusOpen);
		a.Bind(IPAddress::Any, 8081);
		assert(a.m_Status == StatusBound);

		a.Listen();
		assert(a.m_Status == StatusListening);

		a.Close();
		assert(a.m_Status == StatusClose);
	}
}
